#include "HttpServer.hpp"
#include "Util.hpp"
#include <memory>
#include <vector>

const std::string SEP = "\r\n";//分隔符(空行)
const std::string DefaultHome = "./wwwroot/";//wed根目录
const std::string DefaultFile = "indix.html";//默认文件
const std::string err_page = "./wwwroot/err_404.html";//404状态码默认文件


static void usage(char proc[])
{
    std::cout << "Usage:\n\t" << proc << "serverPort" << std::endl;
}

// 解析请求
class HttpRequest
{
public:
    HttpRequest() : _path(DefaultHome)
    {
    }

    // 打印请求的相关信息
    void Print()
    {
        logMessage(Info, "method:%s,url:%s,version:%s", _method.c_str(), _url.c_str(), _version.c_str());

        for (const auto &line : _body)
        {
            logMessage(Debug, "-%s", line.c_str());
        }

        logMessage(Info, "read file:%s done", _path.c_str());
        logMessage(Info, "get suffix:%s", _suffix.c_str());
    }

    ~HttpRequest() {}

public:
    std::string _method;            // 方法
    std::string _url;               // 请求
    std::string _version;           // 版本
    std::vector<std::string> _body; // 请求报头

    std::string _path; // 访问的文件路径
    std::string _suffix;
};

// 请求反序列化 string -> struct
HttpRequest Deserialize(std::string &message)
{
    // 提取并解析第一行
    std::string line;
    HttpRequest hr;
    Util::ReadOneLine(message, line, SEP);
    Util::ParseLine(line, hr._method, hr._url, hr._version);

    // 提取请求报头
    while (!message.empty())
    {
        Util::ReadOneLine(message, line, SEP);
        hr._body.push_back(line);
    }

    if (hr._url == "/")
        hr._path += DefaultFile;
    else
        hr._path += hr._url;

    auto pos = hr._url.rfind(".");
    if (pos == std::string::npos)
        hr._suffix = ".html";
    else
        hr._suffix = hr._url.substr(pos);

    return hr;
}

// 获取请求资源的后缀
std::string GetContentType(const std::string&suffix)
{
    std::string res = "Content-Type: ";
    if (suffix == ".html" || suffix == ".htm")
        res += "text/html";
    else if (suffix == ".css")
        res += "text/css";
    else if (suffix == ".js")
        res += "application/x-javascript";
    else if (suffix == ".png")
        res += "image/png";
    else if (suffix == ".jpg")
        res += "image/jpeg";
    else
    {
    }

    return res;
}

// 返回响应
std::string HandlerHttp(std::string message)
{
    std::cout << "----------------------------------------------" << std::endl;
    // std::cout<<message<<std::endl;
    HttpRequest hr = Deserialize(message);
    hr.Print();

    // 响应有四部分：状态行，响应报头，空行，有效载荷
    // 状态行有，服务器版本，状态码，状态码描述
    // 响应报头包含有效载荷长度，类型，用户信息等等
    std::string response; // 响应
    std::string body;     // 有效载荷
    if (Util::ReadFile(hr._path, body))
    {
        response += "HTTP/1.0 200 OK" + SEP; // 状态行
        response += "Content-Length: " + std::to_string(body.size()) + SEP;
        response += GetContentType(hr._suffix) + SEP;
        response += SEP; // 空行
        response += body;
    }
    else
    {
        response += "HTTP/1.0 404 Not Found" + SEP; // 状态行
        Util::ReadFile(err_page,body);
        response += "Content-Length: " + std::to_string(body.size()) + SEP;
        response += GetContentType(".html") + SEP;
        response+=SEP;//
        response+=body;
    }

    return response;
}

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        usage(argv[0]);
        exit(USAGE_ERR);
    }
    uint16_t port = atoi(argv[1]);

    std::unique_ptr<HttpServer> hs(new HttpServer(HandlerHttp, port));
    hs->InitServer();
    hs->Start();
}